package spe.model.notation;


import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;

import spe.model.spem.NodeElement;
import spe.model.spem.NodeElementImpl;

/**
 * 	Author: Dao Anh Vu
 * 	Link is used to impress the relationship between two NodeElement on diagram
 */
public class Link extends NodeElementImpl
{
	public static final int NOTSPECIFIED = 0;
	public static final int EXTENDED = 1;
	public static final int BELONG_TO = 2;
	public static final int TRACE = 3;
	public static final int PERFORM = 4;
	
	private int type = 0;
	private NodeElement source, target;
	private Label label;
	private List<Point> bendPoints = new ArrayList<Point>();
	//protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
	
	public Label getLabel() 
	{
		if (label == null) {
			//label = (Label) getFactory().create("spe.label");
			label = new Label();
			addPropertyChangeListener(label);
		}
		return label;
	}

	public void setLabel(Label label) {
		this.label = label;
	}

	public void addBendPoint(Point bendPoint) {
		bendPoints.add(bendPoint);
		firePropertyChange("bendPointAdd", null, bendPoint);
	}

	public void addBendPoint(int index, Point bendPoint) {
		bendPoints.add(index, bendPoint);
		firePropertyChange("bendPointAdd", null, bendPoint);
	}

	public void setBendPoint(int index, Point newBendPoint) {
		Point oldBendPoint = bendPoints.get(index);
		bendPoints.set(index, newBendPoint);
		firePropertyChange("bendPointSet", oldBendPoint, newBendPoint);
	}

	public void removeBendPoint(Point bendPoint) {
		bendPoints.remove(bendPoint);
		firePropertyChange("bendPointRemove", bendPoint, null);
	}

	public void removeBendPoint(int index) {
		Point bendPoint = bendPoints.get(index);
		bendPoints.remove(index);
		firePropertyChange("bendPointRemove", bendPoint, null);
	}

	public List<Point> getBendPoints() {
		return bendPoints;
	}

	public void setSource(NodeElement newSource) {
		source = newSource;
	}

	public NodeElement getSource() {
		return source;
	}

	public void setTarget(NodeElement newTarget) {
		target = newTarget;
	}

	public NodeElement getTarget() {
		return target;
	}

	private SPEMDiagram getRootContainer() 
	{
		NodeElement source = getSource();
		if (source == null) return null;
		SPEMDiagram container = source.getContainer();
		/*
		while (container != null && container instanceof NodeElement) {
			container = ((NodeElement)container).getContainer();
		}*/
		return container;
	}
	
	public void propertyChange(PropertyChangeEvent evt) 
	{
		String eventName = evt.getPropertyName();
		if (eventName.equals("to")) {
			if (getSource() == null)
				return;
			SPEMDiagram rootContainer = getRootContainer();
			if (rootContainer == null) return;
			
			NodeElement newTarget = rootContainer.getNodeElementById((String) evt.getNewValue());
			NodeElement oldTarget = rootContainer.getNodeElementById((String) evt.getOldValue());
			
			if (oldTarget != null) 
			{
				oldTarget.removeArrivingEdge(this);
			}
			
			if (newTarget != null) {
				newTarget.addArrivingEdge(this);
			}
			getSource().propertyChange(
					new PropertyChangeEvent(this, "leavingEdgeRefresh", null, null));
		} else {
			firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
		}
	}

	public void setConnectionType(int type)
	{
		this.type = type;
	}
	
	public int getConnectionType() 
	{
		return type;
	}
}
